package com.open.common.util;

import org.apache.http.HttpResponse;
import org.apache.http.client.CookieStore;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class HttpClientUtil {
    private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    private static final String UA = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E; Shuame)";

    // 自定义重试策略
    private static HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
        @Override
        public boolean retryRequest(IOException e, int i, HttpContext httpContext) {
            if (i >= 3) {
                return false;
            }

            if (e instanceof SocketTimeoutException) {
                logger.info("SocketTimeoutException count :{}", i);
                return true;
            }

            if (e instanceof SSLException) {
                logger.info("SSLException count :{}", i);
                return true;
            }
            if (e instanceof ConnectTimeoutException) {
                logger.info("ConnectTimeoutException count :{}", i);
                return true;
            }
            return false;
        }
    };

    /**
     * 获得<code>timeOut</code> 超时的一个get请求
     *
     * @param url
     * @param timeOut
     * @return
     */
    public static HttpGet getTimeOutHttpGet(String url, int timeOut) {
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeOut).setConnectTimeout(timeOut).build();
        httpGet.setConfig(requestConfig);
        return httpGet;
    }

    /**
     * 获得一个超时的post请求
     *
     * @param url
     * @param timeOut
     * @return
     */
    public static HttpPost getTimeOutHttpPost(String url, int timeOut) {
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeOut).setConnectTimeout(timeOut).build();
        httpPost.setConfig(requestConfig);
        return httpPost;
    }

    /**
     * 获取一个支持http，https，会话管理，自动重试的httpclient实例
     *
     * @param cookieStore
     * @return
     * @throws KeyManagementException
     * @throws NoSuchAlgorithmException
     */
    public static CloseableHttpClient getHttpClient(CookieStore cookieStore) throws KeyManagementException, NoSuchAlgorithmException {
        SSLContext sslContext = createIgnoreVerifySSL();
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", new SSLConnectionSocketFactory(sslContext)).build();
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(10 * 1000).build();
        CloseableHttpClient closeableHttpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).setRetryHandler(httpRequestRetryHandler).setUserAgent(UA).setDefaultSocketConfig(socketConfig).setConnectionManager(poolingHttpClientConnectionManager).build();
        return closeableHttpClient;
    }


    public static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("SSLv3");
        X509TrustManager trustManager = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        sslContext.init(null, new TrustManager[]{trustManager}, null);
        return sslContext;
    }

//    /**
//     * selenium cookie 转换为 httpclient cookie
//     * @param cookie
//     * @param domain
//     * @return
//     */
//    public static Cookie SeleniumCookie2HttpclientCookie(org.openqa.selenium.Cookie cookie, String domain) {
//        BasicClientCookie basicClientCookie = new BasicClientCookie(cookie.getName(), cookie.getValue());
//        basicClientCookie.setDomain(domain);
//        return basicClientCookie;
//    }

    /**
     * 保存图片
     *
     * @param httpClient
     * @param get
     * @param filePath
     * @throws IOException
     */
    public static void saveImageFile(HttpClient httpClient, HttpGet get, String filePath) throws IOException {
        HttpResponse closeableHttpResponse = httpClient.execute(get);
        BufferedImage image = ImageIO.read(closeableHttpResponse.getEntity().getContent());
        ImageIO.write(image, "png", new File(filePath));
        EntityUtils.consume(closeableHttpResponse.getEntity());
    }


}
